#ifndef __ECONOMY_SHOP_H__
#define __ECONOMY_SHOP_H__

#include <map>
#include <set>
#include <mutex>
#include "GameSingleton.h"
#include "Engine/GameGuid.h"
#include "Expand/IPlugin.h"
#include "Engine/Point3.hpp"

namespace PocketSurvival
{
    class AuthPlugin;
    class SubsystemPlayers;
}

using namespace PocketSurvival;
using namespace PocketSurvival::Engine;

namespace Economy
{
    class EconomyAPI;

    enum class ShopType
    {
        Shop,
        Shell
    };

    struct ShopData
    {
        Point3 point;           // 位置
        int32_t value;          // 方块id
        uint32_t count;         // 数量
        uint32_t price;         // 价格
        ShopType shopType;      // 商店类型

        ShopData() = default;
        inline explicit ShopData(const Point3 &thePoint, int32_t theValue, uint32_t theCount, uint32_t thePrice, ShopType type) : 
            point(thePoint),
            value(theValue),
            count(theCount),
            price(thePrice),
            shopType(type) {}

        friend inline void to_json(nlohmann::json &json, const ShopData &shopData)
        {
            json = {
                { "point", shopData.point },
                { "value", shopData.value },
                { "count", shopData.count },
                { "price", shopData.price },
                { "type", (uint8_t)shopData.shopType }};
        }
        friend inline void from_json(const nlohmann::json &json, ShopData &shopData)
        {
            shopData.point = json["point"].get<Point3>();
            shopData.value = json["value"].get<int32_t>();
            shopData.count = json["count"].get<uint32_t>();
            shopData.price = json["price"].get<uint32_t>();
            shopData.shopType = (ShopType)json["type"].get<uint8_t>();
        }
    };

    class EconomyShop : public SimpleSingletonItem
    {
        friend class PocketSurvival::SimpleSingleton;
        friend class ShopPlayerEvent;

    private:
        EconomyAPI *m_economyAPI;
        AuthPlugin *m_authPlugin;

        std::set<GameGuid> m_editPlayer;
        std::mutex m_editMutex;

        std::map<std::string, std::vector<ShopData>> m_shopMap;
        std::mutex m_shopMapMutex;

        std::map<GameGuid, ShopData> m_createShopPlayer;
        std::mutex m_createShopMutex;

    private:
        EconomyShop() = default;
        ~EconomyShop();
        EconomyShop(const EconomyShop &) = delete;
        EconomyShop(EconomyShop &&) = delete;
        EconomyShop &operator=(const EconomyShop &) = delete;
        EconomyShop &operator=(EconomyShop &&) = delete;

    public:
        void load();
        void save();

        ShopData *getShopData(const Point3 &point);
        bool addShop(const ShopData &shopData);
        bool removeShop(const Point3 &point);

        void processCmd(IPlugin::ChatObj &chatObj, std::vector<std::string> &cmdDataVec);

    };
    
} // namespace Economy

#endif
